// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: zijin

// bazel build //cc/coin2/strategy/util:moving_window_unittest

#include "coin2/strategy/util/moving_window.h"

#include <algorithm>
#include <cmath>
#include <deque>
#include <random>
#include <utility>
#include <vector>

#include <gtest/gtest.h>
#include <sys/types.h>

namespace coin2::strategy::util {

inline double round3(double val) { return round(val * 1000.0) / 1000.0; }

int64_t prev_ts = 16'000'000'000LL;

TEST(MovingSumTest, Empty) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingSum<double>> ms;
  ms = std::make_unique<MovingSum<double>>(timewindow, multiplier);

  EXPECT_EQ(ms->Size(), 0);
  EXPECT_EQ(ms->GetWindowSize(), 1);
  EXPECT_EQ(ms->Empty(), true);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 0);
}

TEST(MovingSumTest, Basic_Not_Ready) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingSum<double>> ms;
  ms = std::make_unique<MovingSum<double>>(timewindow, multiplier);

  int64_t ts = 0;
  double obj = 100;
  ms->Add(ts + prev_ts, obj);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->GetWindowSize(), 1);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 100);
}

TEST(MovingSumTest, Basic_Not_Ready2) {
  int64_t timewindow = 1;
  int multiplier = 1;
  int64_t ts = 0;
  double obj = 100;
  std::unique_ptr<MovingSum<double>> ms;
  ms = std::make_unique<MovingSum<double>>(timewindow, multiplier);

  ms->Add(ts, obj);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->GetWindowSize(), 1);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 100);

  int64_t ts2 = 1;
  double obj2 = 200;
  ms->Add(ts2, obj2);
  EXPECT_EQ(ms->Size(), 2);
  EXPECT_EQ(ms->GetWindowSize(), 1);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 300);
}

TEST(MovingSumTest, Basic_Not_Ready3) {
  int64_t timewindow = 3;
  int multiplier = 1;
  std::unique_ptr<MovingSum<double>> ms;
  ms = std::make_unique<MovingSum<double>>(timewindow, multiplier);

  int64_t ts = 0;
  double obj = 100;
  ms->Add(ts, obj);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->GetWindowSize(), 3);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 100);

  int64_t ts2 = 1;
  double obj2 = 200;
  ms->Add(ts2, obj2);
  EXPECT_EQ(ms->Size(), 2);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 300);
}

TEST(MovingSumTest, Basic_Ready) {
  int64_t timewindow = 1;
  int multiplier = 1;
  int64_t ts = 0;
  double obj = 100;
  std::unique_ptr<MovingSum<double>> ms;
  ms = std::make_unique<MovingSum<double>>(timewindow, multiplier);

  ms->Add(ts, obj);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->GetWindowSize(), 1);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 100);

  int64_t ts2 = 2;
  double obj2 = 200;
  ms->Add(ts2, obj2);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->GetWindowSize(), 1);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), true);
  EXPECT_EQ(ms->GetSum(), 200);
}

TEST(MovingSumTest, Basic_Ready2) {
  int64_t timewindow = 2;
  int multiplier = 1;
  int64_t ts = 0;
  double obj = 100;
  std::unique_ptr<MovingSum<double>> ms;
  ms = std::make_unique<MovingSum<double>>(timewindow, multiplier);

  ms->Add(ts, obj);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->GetWindowSize(), 2);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), false);
  EXPECT_EQ(ms->GetSum(), 100);

  int64_t ts2 = 3;
  double obj2 = 200;
  ms->Add(ts2, obj2);
  EXPECT_EQ(ms->Size(), 1);
  EXPECT_EQ(ms->Empty(), false);
  EXPECT_EQ(ms->Ready(), true);
  EXPECT_EQ(ms->GetSum(), 200);
}

TEST(MemMovingSumTest, Empty) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  EXPECT_EQ(mms->Size(), 0);
  EXPECT_EQ(mms->GetWindowSize(), 5);
  EXPECT_EQ(mms->Empty(), true);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 0);
}

TEST(MemMovingSumTest, Basic_Not_Ready_PushBack) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double obj = 100;
  mms->Add(ts + prev_ts, obj);
  EXPECT_EQ(mms->GetWindowSize(), 5);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 100);
}

TEST(MemMovingSumTest, Basic_Not_Ready_PushBack2) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double obj = 100;
  mms->Add(ts + prev_ts, obj);
  EXPECT_EQ(mms->Size(), 1);
  EXPECT_EQ(mms->GetWindowSize(), 5);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 100);

  int64_t ts2 = 4;
  double obj2 = 200;
  mms->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 300);

  EXPECT_EQ(mms->GetLastData(), 200);
  EXPECT_EQ(mms->GetFirstData(), 100);
  EXPECT_EQ(mms->GetLastTs(), 16000000004);
  EXPECT_EQ(mms->GetFirstTs(), 16000000002);
}

TEST(MemMovingSumTest, Basic_Not_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double obj = 100;
  mms->Add(ts + prev_ts, obj);
  EXPECT_EQ(mms->Size(), 1);
  EXPECT_EQ(mms->GetWindowSize(), 5);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 100);

  int64_t ts2 = 3;
  double obj2 = 200;
  mms->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mms->Size(), 1);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 300);

  EXPECT_EQ(mms->GetLastData(), 300);
  EXPECT_EQ(mms->GetFirstData(), 300);
  EXPECT_EQ(mms->GetLastTs(), 16000000002);
  EXPECT_EQ(mms->GetFirstTs(), 16000000002);
}

TEST(MemMovingSumTest, Basic_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double obj = 100;
  mms->Add(ts + prev_ts, obj);
  EXPECT_EQ(mms->Size(), 1);
  EXPECT_EQ(mms->GetWindowSize(), 5);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 100);
  EXPECT_EQ(mms->GetLastData(), 100);
  EXPECT_EQ(mms->GetFirstData(), 100);
  EXPECT_EQ(mms->GetLastTs(), 16000000002);
  EXPECT_EQ(mms->GetFirstTs(), 16000000002);
  // interval_id_ = interval = 1, real_last_ts = 2, exceed_ts =

  int64_t ts2 = 4;
  double obj2 = 200;
  mms->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetLastData(), 200);
  EXPECT_EQ(mms->GetFirstData(), 100);
  EXPECT_EQ(mms->GetLastTs(), 16000000004);
  EXPECT_EQ(mms->GetFirstTs(), 16000000002);
  EXPECT_EQ(mms->GetSum(), 300);
  // interval_id_ = interval = 2, real_last_ts = 4, exceed_ts = 4 - 2 - 5 < 0, sum = 300

  int64_t ts3 = 10;
  double obj3 = 300;
  mms->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), true);
  EXPECT_EQ(mms->GetLastData(), 300);
  EXPECT_EQ(mms->GetFirstData(), 200);
  EXPECT_EQ(mms->GetLastTs(), 16000000010);
  EXPECT_EQ(mms->GetFirstTs(), 16000000004);
  EXPECT_EQ(mms->GetSum(), 400);
  // interval_id_ = interval = 5, real_last_ts = 10, exceed_ts = 10 - 4 - 5 = 1,
  // ratio = 1/2 = 0.5, res = 500 - 0.5 * 200 = 400

  int64_t ts4 = 11;
  double obj4 = 400;
  mms->Add(ts4 + prev_ts, obj4);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), true);
  EXPECT_EQ(mms->GetSum(), 700);

  EXPECT_EQ(mms->GetLastData(), 700);
  EXPECT_EQ(mms->GetFirstData(), 200);
  EXPECT_EQ(mms->GetLastTs(), 16000000010);
  EXPECT_EQ(mms->GetFirstTs(), 16000000004);
  // interval_id_ = interval = 5
}

TEST(MemMovingSumTest, Intermediate_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double obj = 100;
  mms->Add(ts + prev_ts, obj);

  int64_t ts2 = 4;
  double obj2 = 200;
  mms->Add(ts2 + prev_ts, obj2);

  int64_t ts3 = 10;
  double obj3 = 300;
  mms->Add(ts3 + prev_ts, obj3);

  int64_t ts4 = 11;
  double obj4 = 400;
  mms->Add(ts4 + prev_ts, obj4);

  int64_t ts5 = 13;
  double obj5 = 500;
  mms->Add(ts5 + prev_ts, obj5);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), true);
  EXPECT_EQ(mms->GetSum(), 1200);

  EXPECT_EQ(mms->GetLastData(), 500);
  EXPECT_EQ(mms->GetFirstData(), 700);
  EXPECT_EQ(mms->GetLastTs(), 16000000013);
  EXPECT_EQ(mms->GetFirstTs(), 16000000010);

  int64_t ts6 = 16;
  double obj6 = 600;
  mms->Add(ts6 + prev_ts, obj6);
  EXPECT_EQ(mms->Size(), 3);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), true);
  EXPECT_EQ(mms->GetSum(), 1450);
  // exceed_ts = 16 - 10 - 5 = 1, ratio = 0.5, res = 1800 - 350 = 1450

  EXPECT_EQ(mms->GetLastData(), 600);
  EXPECT_EQ(mms->GetFirstData(), 700);
  EXPECT_EQ(mms->GetLastTs(), 16000000016);
  EXPECT_EQ(mms->GetFirstTs(), 16000000010);
}

TEST(MemMovingSumTest, Basic_Ready_Pushback) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingSum<double>> mms;
  mms = std::make_unique<MemMovingSum<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double obj = 100;
  mms->Add(ts + prev_ts, obj);
  EXPECT_EQ(mms->Size(), 1);
  EXPECT_EQ(mms->GetWindowSize(), 5);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 100);

  EXPECT_EQ(mms->GetLastData(), 100);
  EXPECT_EQ(mms->GetFirstData(), 100);
  EXPECT_EQ(mms->GetLastTs(), 16000000002);
  EXPECT_EQ(mms->GetFirstTs(), 16000000002);
  // interval_id_ = interval = 1

  int64_t ts2 = 4;
  double obj2 = 200;
  mms->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), false);
  EXPECT_EQ(mms->GetSum(), 300);

  EXPECT_EQ(mms->GetLastData(), 200);
  EXPECT_EQ(mms->GetFirstData(), 100);
  EXPECT_EQ(mms->GetLastTs(), 16000000004);
  EXPECT_EQ(mms->GetFirstTs(), 16000000002);
  // interval_id_ = interval = 2

  int64_t ts3 = 10;
  double obj3 = 300;
  mms->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(mms->Size(), 2);
  EXPECT_EQ(mms->Empty(), false);
  EXPECT_EQ(mms->Ready(), true);
  EXPECT_EQ(mms->GetSum(), 400);

  EXPECT_EQ(mms->GetLastData(), 300);
  EXPECT_EQ(mms->GetFirstData(), 200);
  EXPECT_EQ(mms->GetLastTs(), 16000000010);
  EXPECT_EQ(mms->GetFirstTs(), 16000000004);
  // interval_id_ = interval = 5
}

TEST(MovingAverageTest, Empty) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);
  double mean = 0, std = 0;

  EXPECT_EQ(ma->Size(), 0);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), true);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), false);
}

TEST(MovingAverageTest, Basic_Not_Ready) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);
  double mean = 0, std = 0;

  int64_t ts = 1;
  double obj = 100;
  ma->Add(ts + prev_ts, obj);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);
}

TEST(MovingAverageTest, Basic_Not_Ready2) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);
  double mean = 0, std = 0;

  int64_t ts = 1;
  double obj = 100;
  ma->Add(ts + prev_ts, obj);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);

  int64_t ts2 = 2;
  double obj2 = 200;
  ma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(ma->Size(), 2);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);
}

TEST(MovingAverageTest, Basic_Ready) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);
  double mean = 0, std = 0;

  int64_t ts = 1;
  double obj = 100;
  ma->Add(ts + prev_ts, obj);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);

  int64_t ts2 = 3;
  double obj2 = 200;
  ma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 200);
  EXPECT_EQ(std, 0);
}

TEST(MovingAverageTest, Intermeidate) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);
  double mean = 0, std = 0;

  int64_t ts = 2;
  double obj = 100;
  ma->Add(ts + prev_ts, obj);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);

  int64_t ts2 = 3;
  double obj2 = 200;
  ma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(ma->Size(), 2);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  int64_t ts3 = 4;
  double obj3 = 300;
  ma->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(ma->Size(), 2);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 250);
  EXPECT_EQ(std, 50);

  int64_t ts4 = 5;
  double obj4 = 400;
  ma->Add(ts4 + prev_ts, obj4);
  EXPECT_EQ(ma->Size(), 2);
  EXPECT_EQ(ma->GetWindowSize(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 350);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(ma->GetLastData(), 400);
  EXPECT_EQ(ma->GetFirstData(), 300);
  EXPECT_EQ(ma->GetLastTs(), 16000000005);
  EXPECT_EQ(ma->GetFirstTs(), 16000000004);
}

TEST(MovingAverageTest, Intermeidate2) {
  int64_t timewindow = 2;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);

  double mean = 0, std = 0;
  int64_t ts = 1;
  double obj = 100;
  ma->Add(ts + prev_ts, obj);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->GetWindowSize(), 2);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);

  int64_t ts2 = 3;
  double obj2 = 200;
  ma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(ma->Size(), 2);
  EXPECT_EQ(ma->GetWindowSize(), 2);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  int64_t ts3 = 4;
  double obj3 = 300;
  ma->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(ma->Size(), 2);
  EXPECT_EQ(ma->GetWindowSize(), 2);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 250);
  EXPECT_EQ(std, 50);

  int64_t ts4 = 5;
  double obj4 = 400;
  ma->Add(ts4 + prev_ts, obj4);
  EXPECT_EQ(ma->Size(), 3);
  EXPECT_EQ(ma->GetWindowSize(), 2);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 300);
  EXPECT_EQ(round3(std), 81.650);

  EXPECT_EQ(ma->GetLastData(), 400);
  EXPECT_EQ(ma->GetFirstData(), 200);
  EXPECT_EQ(ma->GetLastTs(), 16000000005);
  EXPECT_EQ(ma->GetFirstTs(), 16000000003);
}

TEST(MovingAverageTest, Intermeidate3) {
  int64_t timewindow = 10;
  int multiplier = 1;
  std::unique_ptr<MovingAverage<double>> ma;
  ma = std::make_unique<MovingAverage<double>>(timewindow, multiplier);

  double mean = 0, std = 0;
  ma->Add(1 + prev_ts, 100);
  ma->Add(2 + prev_ts, 200);
  ma->Add(3 + prev_ts, 300);
  EXPECT_EQ(ma->Size(), 3);
  EXPECT_EQ(ma->GetWindowSize(), 10);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), false);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 200);
  EXPECT_EQ(round3(std), 81.650);

  EXPECT_EQ(ma->GetLastData(), 300);
  EXPECT_EQ(ma->GetFirstData(), 100);
  EXPECT_EQ(ma->GetLastTs(), 16000000003);
  EXPECT_EQ(ma->GetFirstTs(), 16000000001);

  ma->Add(12 + prev_ts, 400);
  EXPECT_EQ(ma->Size(), 3);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 300);
  EXPECT_EQ(round3(std), 81.650);

  EXPECT_EQ(ma->GetLastData(), 400);
  EXPECT_EQ(ma->GetFirstData(), 200);
  EXPECT_EQ(ma->GetLastTs(), 16000000012);
  EXPECT_EQ(ma->GetFirstTs(), 16000000002);

  ma->Add(24 + prev_ts, 500);
  EXPECT_EQ(ma->Size(), 1);
  EXPECT_EQ(ma->Empty(), false);
  EXPECT_EQ(ma->Ready(), true);
  EXPECT_EQ(ma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 500);
  EXPECT_EQ(round3(std), 0);

  EXPECT_EQ(ma->GetLastData(), 500);
  EXPECT_EQ(ma->GetFirstData(), 500);
  EXPECT_EQ(ma->GetLastTs(), 16000000024);
  EXPECT_EQ(ma->GetFirstTs(), 16000000024);
}

TEST(MemMovingAverageTest, Basic) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  EXPECT_EQ(mma->Size(), 0);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), true);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), false);
}

TEST(MemMovingAverageTest, Basic_Not_Ready_PushBack) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  int64_t ts = 1;
  int obj = 100;
  mma->Add(ts + prev_ts, obj);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);
}

TEST(MemMovingAverageTest, Basic_Not_Ready_PushBack2) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  int64_t ts = 1;
  int obj = 100;
  mma->Add(ts + prev_ts, obj);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);

  int64_t ts2 = 2;
  int obj2 = 200;
  mma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 200);
  EXPECT_EQ(mma->GetFirstData(), 100);
  EXPECT_EQ(mma->GetLastTs(), 16000000002);
  EXPECT_EQ(mma->GetFirstTs(), 16000000001);
}

TEST(MemMovingAverageTest, Basic_Not_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  int64_t ts = 2;
  double obj = 100;
  mma->Add(ts + prev_ts, obj);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);
  // interval_id_ = interval = 2/2 =1

  int64_t ts2 = 3;
  double obj2 = 200;
  mma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 300);
  EXPECT_EQ(mma->GetFirstData(), 300);
  EXPECT_EQ(mma->GetLastTs(), 16000000002);
  EXPECT_EQ(mma->GetFirstTs(), 16000000002);
}

TEST(MemMovingAverageTest, Basic_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  int64_t ts = 2;
  double obj = 100;
  mma->Add(ts + prev_ts, obj);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);
  // interval_id_ = interval = 2/2 =1

  int64_t ts2 = 4;
  double obj2 = 200;
  mma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 200);
  EXPECT_EQ(mma->GetFirstData(), 100);
  EXPECT_EQ(mma->GetLastTs(), 16000000004);
  EXPECT_EQ(mma->GetFirstTs(), 16000000002);

  int64_t ts3 = 10;
  double obj3 = 300;
  mma->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), true);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 250);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 300);
  EXPECT_EQ(mma->GetFirstData(), 200);
  EXPECT_EQ(mma->GetLastTs(), 16000000010);
  EXPECT_EQ(mma->GetFirstTs(), 16000000004);

  int64_t ts4 = 11;
  double obj4 = 400;
  mma->Add(ts4 + prev_ts, obj4);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), true);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 300);
  EXPECT_EQ(round3(std), 81.650);

  EXPECT_EQ(mma->GetLastData(), 700);
  EXPECT_EQ(mma->GetFirstData(), 200);
  EXPECT_EQ(mma->GetLastTs(), 16000000010);
  EXPECT_EQ(mma->GetFirstTs(), 16000000004);
}

TEST(MemMovingAverageTest, Basic_Ready_Pushback) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  int64_t ts = 2;
  double obj = 100;
  mma->Add(ts + prev_ts, obj);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->GetWindowSize(), 5);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 100);
  EXPECT_EQ(std, 0);
  // interval_id_ = interval = 2/2 =1

  EXPECT_EQ(mma->GetLastData(), 100);
  EXPECT_EQ(mma->GetFirstData(), 100);
  EXPECT_EQ(mma->GetLastTs(), 16000000002);
  EXPECT_EQ(mma->GetFirstTs(), 16000000002);

  int64_t ts2 = 4;
  double obj2 = 200;
  mma->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 200);
  EXPECT_EQ(mma->GetFirstData(), 100);
  EXPECT_EQ(mma->GetLastTs(), 16000000004);
  EXPECT_EQ(mma->GetFirstTs(), 16000000002);

  int64_t ts3 = 10;
  double obj3 = 300;
  mma->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), true);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 250);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 300);
  EXPECT_EQ(mma->GetFirstData(), 200);
  EXPECT_EQ(mma->GetLastTs(), 16000000010);
  EXPECT_EQ(mma->GetFirstTs(), 16000000004);
}

TEST(MemMovingAverageTest, Intermediate) {
  int64_t timewindow = 10;
  int64_t merge_window = 3;
  std::unique_ptr<MemMovingAverage<double>> mma;
  mma = std::make_unique<MemMovingAverage<double>>(timewindow, merge_window);
  double mean = 0, std = 0;

  EXPECT_EQ(mma->GetWindowSize(), 10);

  mma->Add(1 + prev_ts, 100);
  mma->Add(2 + prev_ts, 200);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 150);
  EXPECT_EQ(std, 50);

  EXPECT_EQ(mma->GetLastData(), 200);
  EXPECT_EQ(mma->GetFirstData(), 100);
  EXPECT_EQ(mma->GetLastTs(), 16000000002);
  EXPECT_EQ(mma->GetFirstTs(), 16000000001);

  mma->Add(3 + prev_ts, 300);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), false);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 200);
  EXPECT_EQ(round3(std), 81.650);

  EXPECT_EQ(mma->GetLastData(), 500);
  EXPECT_EQ(mma->GetFirstData(), 100);
  EXPECT_EQ(mma->GetLastTs(), 16000000002);
  EXPECT_EQ(mma->GetFirstTs(), 16000000001);

  mma->Add(15 + prev_ts, 400);
  EXPECT_EQ(mma->Size(), 2);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), true);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 300);
  EXPECT_EQ(round3(std), 81.650);

  EXPECT_EQ(mma->GetLastData(), 400);
  EXPECT_EQ(mma->GetFirstData(), 500);
  EXPECT_EQ(mma->GetLastTs(), 16000000015);
  EXPECT_EQ(mma->GetFirstTs(), 16000000002);

  mma->Add(16 + prev_ts, 250);
  EXPECT_EQ(mma->Size(), 1);
  EXPECT_EQ(mma->Empty(), false);
  EXPECT_EQ(mma->Ready(), true);
  EXPECT_EQ(mma->GetStatistics(&mean, &std), true);
  EXPECT_EQ(mean, 325);
  EXPECT_EQ(std, 75);

  EXPECT_EQ(mma->GetLastData(), 650);
  EXPECT_EQ(mma->GetFirstData(), 650);
  EXPECT_EQ(mma->GetLastTs(), 16000000015);
  EXPECT_EQ(mma->GetFirstTs(), 16000000015);
}

TEST(MovingUniqueTest, Empty) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingUnique<double>> mu;
  mu = std::make_unique<MovingUnique<double>>(timewindow);

  EXPECT_EQ(mu->Size(), 0);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), true);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 0);
}

TEST(MovingUniqueTest, Basic_Not_Update) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingUnique<double>> mu;
  mu = std::make_unique<MovingUnique<double>>(timewindow);

  EXPECT_EQ(mu->Size(), 0);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), true);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 0);

  int64_t ts = 1;
  double obj = 100;
  mu->Add(ts + prev_ts, obj);
  EXPECT_EQ(mu->Size(), 1);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);
}

TEST(MovingUniqueTest, Basic_Update) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingUnique<double>> mu;
  mu = std::make_unique<MovingUnique<double>>(timewindow);

  EXPECT_EQ(mu->Size(), 0);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), true);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 0);

  int64_t ts = 1;
  double obj = 100;
  mu->Add(ts + prev_ts, obj);
  EXPECT_EQ(mu->Size(), 1);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);

  EXPECT_EQ(mu->GetLastData(), 100);
  EXPECT_EQ(mu->GetFirstData(), 100);
  EXPECT_EQ(mu->GetLastTs(), 16000000001);
  EXPECT_EQ(mu->GetFirstTs(), 16000000001);

  int64_t ts2 = 3;
  double obj2 = 200;
  mu->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mu->Size(), 1);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);

  EXPECT_EQ(mu->GetLastData(), 200);
  EXPECT_EQ(mu->GetFirstData(), 200);
  EXPECT_EQ(mu->GetLastTs(), 16000000003);
  EXPECT_EQ(mu->GetFirstTs(), 16000000003);
}

TEST(MovingUniqueTest, Basic_Check_Unique) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingUnique<double>> mu;
  mu = std::make_unique<MovingUnique<double>>(timewindow);

  EXPECT_EQ(mu->Size(), 0);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), true);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 0);

  int64_t ts = 1;
  double obj = 100;
  mu->Add(ts + prev_ts, obj);
  EXPECT_EQ(mu->Size(), 1);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);

  EXPECT_EQ(mu->GetLastData(), 100);
  EXPECT_EQ(mu->GetFirstData(), 100);
  EXPECT_EQ(mu->GetLastTs(), 16000000001);
  EXPECT_EQ(mu->GetFirstTs(), 16000000001);

  int64_t ts2 = 2;
  double obj2 = 100;
  mu->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mu->Size(), 2);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);

  EXPECT_EQ(mu->GetLastData(), 100);
  EXPECT_EQ(mu->GetFirstData(), 100);
  EXPECT_EQ(mu->GetLastTs(), 16000000002);
  EXPECT_EQ(mu->GetFirstTs(), 16000000001);

  int64_t ts3 = 3;
  double obj3 = 200;
  mu->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(mu->Size(), 2);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 2);

  EXPECT_EQ(mu->GetLastData(), 200);
  EXPECT_EQ(mu->GetFirstData(), 100);
  EXPECT_EQ(mu->GetLastTs(), 16000000003);
  EXPECT_EQ(mu->GetFirstTs(), 16000000002);
}

TEST(MovingUniqueTest, Basic_Check_Unique2) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingUnique<double>> mu;
  mu = std::make_unique<MovingUnique<double>>(timewindow);

  EXPECT_EQ(mu->Size(), 0);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), true);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 0);

  int64_t ts = 1;
  double obj = 100;
  mu->Add(ts + prev_ts, obj);
  EXPECT_EQ(mu->Size(), 1);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);

  EXPECT_EQ(mu->GetLastData(), 100);
  EXPECT_EQ(mu->GetFirstData(), 100);
  EXPECT_EQ(mu->GetLastTs(), 16000000001);
  EXPECT_EQ(mu->GetFirstTs(), 16000000001);

  int64_t ts2 = 2;
  double obj2 = 200;
  mu->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mu->Size(), 2);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 2);

  EXPECT_EQ(mu->GetLastData(), 200);
  EXPECT_EQ(mu->GetFirstData(), 100);
  EXPECT_EQ(mu->GetLastTs(), 16000000002);
  EXPECT_EQ(mu->GetFirstTs(), 16000000001);

  int64_t ts3 = 3;
  double obj3 = 200;
  mu->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(mu->Size(), 2);
  EXPECT_EQ(mu->GetWindowSize(), 1);
  EXPECT_EQ(mu->Empty(), false);
  EXPECT_EQ(mu->Ready(), false);
  EXPECT_EQ(mu->GetUnique(), 1);

  EXPECT_EQ(mu->GetLastData(), 200);
  EXPECT_EQ(mu->GetFirstData(), 200);
  EXPECT_EQ(mu->GetLastTs(), 16000000003);
  EXPECT_EQ(mu->GetFirstTs(), 16000000002);
}

TEST(MovingObjectTest, Empty) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingObject<double>> mo;
  mo = std::make_unique<MovingObject<double>>(timewindow);

  EXPECT_EQ(mo->Size(), 0);
  EXPECT_EQ(mo->GetWindowSize(), 1);
  EXPECT_EQ(mo->Empty(), true);
}

TEST(MovingObjectTest, Basic_Not_Update) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingObject<double>> mo;
  mo = std::make_unique<MovingObject<double>>(timewindow);

  int64_t ts = 0;
  double obj = 100;
  mo->Add(ts + prev_ts, obj);
  EXPECT_EQ(mo->Size(), 1);
  EXPECT_EQ(mo->GetWindowSize(), 1);
  EXPECT_EQ(mo->Empty(), false);
}

TEST(MovingObjectTest, Basic_Not_Update2) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingObject<double>> mo;
  mo = std::make_unique<MovingObject<double>>(timewindow);

  int64_t ts = 0;
  double obj = 100;
  mo->Add(ts + prev_ts, obj);
  EXPECT_EQ(mo->Size(), 1);
  EXPECT_EQ(mo->GetWindowSize(), 1);
  EXPECT_EQ(mo->Empty(), false);

  int64_t ts2 = 1;
  double obj2 = 200;
  mo->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mo->Size(), 2);
  EXPECT_EQ(mo->GetWindowSize(), 1);
  EXPECT_EQ(mo->Empty(), false);
}

TEST(MovingObjectTest, Basic_Update) {
  int64_t timewindow = 1;
  std::unique_ptr<MovingObject<double>> mo;
  mo = std::make_unique<MovingObject<double>>(timewindow);

  int64_t ts = 0;
  double obj = 100;
  mo->Add(ts + prev_ts, obj);
  EXPECT_EQ(mo->Size(), 1);
  EXPECT_EQ(mo->GetWindowSize(), 1);
  EXPECT_EQ(mo->Empty(), false);

  int64_t ts2 = 2;
  double obj2 = 200;
  mo->Add(ts2 + prev_ts, obj2);
  EXPECT_EQ(mo->Size(), 1);
  EXPECT_EQ(mo->GetWindowSize(), 1);
  EXPECT_EQ(mo->Empty(), false);
}

TEST(VolumeWeightedMovingAverageTest, Empty) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<VolumeWeightedMovingAverage<double>> vwma;
  vwma = std::make_unique<VolumeWeightedMovingAverage<double>>(timewindow, multiplier);

  EXPECT_EQ(vwma->Size(), 0);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), true);
  EXPECT_EQ(vwma->Ready(), false);
}

TEST(VolumeWeightedMovingAverageTest, Basic_Not_Ready) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<VolumeWeightedMovingAverage<double>> vwma;
  vwma = std::make_unique<VolumeWeightedMovingAverage<double>>(timewindow, multiplier);

  int64_t ts = 0;
  double p = 100, q = 20;
  vwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(vwma->Size(), 1);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 100);
}

TEST(VolumeWeightedMovingAverageTest, Basic_Not_Ready2) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<VolumeWeightedMovingAverage<double>> vwma;
  vwma = std::make_unique<VolumeWeightedMovingAverage<double>>(timewindow, multiplier);

  int64_t ts = 0;
  double p = 100, q = 20;
  vwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(vwma->Size(), 1);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 100);

  int64_t ts2 = 1;
  double p2 = 200, q2 = 30;
  vwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(vwma->Size(), 2);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 160);
}

TEST(VolumeWeightedMovingAverageTest, Basic_Ready) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<VolumeWeightedMovingAverage<double>> vwma;
  vwma = std::make_unique<VolumeWeightedMovingAverage<double>>(timewindow, multiplier);

  int64_t ts = 1;
  double p = 100, q = 20;
  vwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(vwma->Size(), 1);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 100);

  int64_t ts2 = 3;
  double p2 = 200, q2 = 30;
  vwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(vwma->Size(), 1);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), true);
  EXPECT_EQ(vwma->GetAverage(), 200);
}

TEST(VolumeWeightedMovingAverageTest, Intermeidate) {
  int64_t timewindow = 1;
  int multiplier = 1;
  std::unique_ptr<VolumeWeightedMovingAverage<double>> vwma;
  vwma = std::make_unique<VolumeWeightedMovingAverage<double>>(timewindow, multiplier);

  int64_t ts = 2;
  double p = 100, q = 20;
  vwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(vwma->Size(), 1);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 100);

  int64_t ts2 = 3;
  double p2 = 200, q2 = 30;
  vwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(vwma->Size(), 2);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 160);

  int64_t ts3 = 4;
  double p3 = 300, q3 = 40;
  vwma->Add(ts3 + prev_ts, p3, q3);
  EXPECT_EQ(vwma->Size(), 2);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), true);
  EXPECT_EQ(round3(vwma->GetAverage()), 257.143);

  int64_t ts4 = 5;
  double p4 = 400, q4 = 50;
  vwma->Add(ts4 + prev_ts, p4, q4);
  EXPECT_EQ(vwma->Size(), 2);
  EXPECT_EQ(vwma->GetWindowSize(), 1);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), true);
  EXPECT_EQ(round3(vwma->GetAverage()), 355.556);

  EXPECT_EQ(vwma->GetLastData(), 20000);
  EXPECT_EQ(vwma->GetFirstData(), 12000);
  EXPECT_EQ(vwma->GetLastTs(), 16000000005);
  EXPECT_EQ(vwma->GetFirstTs(), 16000000004);
}

TEST(VolumeWeightedMovingAverageTest, Intermeidate2) {
  int64_t timewindow = 2;
  int multiplier = 1;
  std::unique_ptr<VolumeWeightedMovingAverage<double>> vwma;
  vwma = std::make_unique<VolumeWeightedMovingAverage<double>>(timewindow, multiplier);

  int64_t ts = 2;
  double p = 100, q = 20;
  vwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(vwma->Size(), 1);
  EXPECT_EQ(vwma->GetWindowSize(), 2);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 100);

  int64_t ts2 = 3;
  double p2 = 200, q2 = 30;
  vwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(vwma->Size(), 2);
  EXPECT_EQ(vwma->GetWindowSize(), 2);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(vwma->GetAverage(), 160);

  int64_t ts3 = 4;
  double p3 = 300, q3 = 40;
  vwma->Add(ts3 + prev_ts, p3, q3);
  EXPECT_EQ(vwma->Size(), 3);
  EXPECT_EQ(vwma->GetWindowSize(), 2);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), false);
  EXPECT_EQ(round3(vwma->GetAverage()), 222.222);

  int64_t ts4 = 5;
  double p4 = 400, q4 = 50;
  vwma->Add(ts4 + prev_ts, p4, q4);
  EXPECT_EQ(vwma->Size(), 3);
  EXPECT_EQ(vwma->GetWindowSize(), 2);
  EXPECT_EQ(vwma->Empty(), false);
  EXPECT_EQ(vwma->Ready(), true);
  EXPECT_EQ(round3(vwma->GetAverage()), 316.667);

  EXPECT_EQ(vwma->GetLastData(), 20000);
  EXPECT_EQ(vwma->GetFirstData(), 6000);
  EXPECT_EQ(vwma->GetLastTs(), 16000000005);
  EXPECT_EQ(vwma->GetFirstTs(), 16000000003);
}

TEST(MemVolumeWeightedMovingAverageTest, Empty) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemVolumeWeightedMovingAverage<double>> mvwma;
  mvwma = std::make_unique<MemVolumeWeightedMovingAverage<double>>(timewindow, merge_window);

  EXPECT_EQ(mvwma->Size(), 0);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), true);
  EXPECT_EQ(mvwma->Ready(), false);
}

TEST(MemVolumeWeightedMovingAverageTest, Basic_Not_Ready_PushBack) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemVolumeWeightedMovingAverage<double>> mvwma;
  mvwma = std::make_unique<MemVolumeWeightedMovingAverage<double>>(timewindow, merge_window);
  int64_t ts = 1;
  double p = 100, q = 20;
  mvwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(mvwma->Size(), 1);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 100);
}

TEST(MemVolumeWeightedMovingAverageTest, Basic_Not_Ready_PushBack2) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemVolumeWeightedMovingAverage<double>> mvwma;
  mvwma = std::make_unique<MemVolumeWeightedMovingAverage<double>>(timewindow, merge_window);

  int64_t ts = 1;
  double p = 100, q = 20;
  mvwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(mvwma->Size(), 1);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 100);

  int64_t ts2 = 2;
  double p2 = 200, q2 = 30;
  mvwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(mvwma->Size(), 2);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 160);

  EXPECT_EQ(mvwma->GetLastData(), 6000);
  EXPECT_EQ(mvwma->GetFirstData(), 2000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000002);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000001);
}

TEST(MemVolumeWeightedMovingAverageTest, Basic_Not_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemVolumeWeightedMovingAverage<double>> mvwma;
  mvwma = std::make_unique<MemVolumeWeightedMovingAverage<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double p = 100, q = 20;
  mvwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(mvwma->Size(), 1);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 100);

  int64_t ts2 = 3;
  double p2 = 200, q2 = 30;
  mvwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(mvwma->Size(), 1);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 160);

  EXPECT_EQ(mvwma->GetLastData(), 8000);
  EXPECT_EQ(mvwma->GetFirstData(), 8000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000002);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000002);
}

TEST(MemVolumeWeightedMovingAverageTest, Basic_Ready_Back) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemVolumeWeightedMovingAverage<double>> mvwma;
  mvwma = std::make_unique<MemVolumeWeightedMovingAverage<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double p = 100, q = 20;
  mvwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(mvwma->Size(), 1);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 100);

  int64_t ts2 = 4;
  double p2 = 200, q2 = 30;
  mvwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(mvwma->Size(), 2);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 160);

  EXPECT_EQ(mvwma->GetLastData(), 6000);
  EXPECT_EQ(mvwma->GetFirstData(), 2000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000004);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000002);

  int64_t ts3 = 10;
  double p3 = 300, q3 = 40;
  mvwma->Add(ts3 + prev_ts, p3, q3);
  EXPECT_EQ(mvwma->Size(), 2);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), true);
  EXPECT_EQ(round3(mvwma->GetAverage()), 257.143);

  EXPECT_EQ(mvwma->GetLastData(), 12000);
  EXPECT_EQ(mvwma->GetFirstData(), 6000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000010);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000004);

  int64_t ts4 = 11;
  double p4 = 400, q4 = 50;
  mvwma->Add(ts4 + prev_ts, p4, q4);
  EXPECT_EQ(mvwma->Size(), 2);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), true);
  EXPECT_EQ(round3(mvwma->GetAverage()), 316.667);

  EXPECT_EQ(mvwma->GetLastData(), 32000);
  EXPECT_EQ(mvwma->GetFirstData(), 6000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000010);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000004);
}

TEST(MemVolumeWeightedMovingAverageTest, Basic_Ready_Pushback) {
  int64_t timewindow = 5;
  int64_t merge_window = 2;
  std::unique_ptr<MemVolumeWeightedMovingAverage<double>> mvwma;
  mvwma = std::make_unique<MemVolumeWeightedMovingAverage<double>>(timewindow, merge_window);

  int64_t ts = 2;
  double p = 100, q = 20;
  mvwma->Add(ts + prev_ts, p, q);
  EXPECT_EQ(mvwma->Size(), 1);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 100);

  int64_t ts2 = 4;
  double p2 = 200, q2 = 30;
  mvwma->Add(ts2 + prev_ts, p2, q2);
  EXPECT_EQ(mvwma->Size(), 2);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), false);
  EXPECT_EQ(mvwma->GetAverage(), 160);

  EXPECT_EQ(mvwma->GetLastData(), 6000);
  EXPECT_EQ(mvwma->GetFirstData(), 2000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000004);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000002);

  int64_t ts3 = 10;
  double p3 = 300, q3 = 40;
  mvwma->Add(ts3 + prev_ts, p3, q3);
  EXPECT_EQ(mvwma->Size(), 2);
  EXPECT_EQ(mvwma->GetWindowSize(), 5);
  EXPECT_EQ(mvwma->Empty(), false);
  EXPECT_EQ(mvwma->Ready(), true);
  EXPECT_EQ(round3(mvwma->GetAverage()), 257.143);

  EXPECT_EQ(mvwma->GetLastData(), 12000);
  EXPECT_EQ(mvwma->GetFirstData(), 6000);
  EXPECT_EQ(mvwma->GetLastTs(), 16000000010);
  EXPECT_EQ(mvwma->GetFirstTs(), 16000000004);
}

TEST(TimeWeightedMovingAverageTest, Empty) {
  int64_t timewindow = 1e6;
  std::unique_ptr<TimeWeightedMovingAverage<double>> twma;
  twma = std::make_unique<TimeWeightedMovingAverage<double>>(timewindow);

  EXPECT_EQ(twma->Size(), 0);
  EXPECT_EQ(twma->GetWindowSize(), 1e6);
  EXPECT_EQ(twma->Empty(), true);
  EXPECT_EQ(twma->Ready(), false);
}

TEST(TimeWeightedMovingAverageTest, Basic_Not_Ready) {
  int64_t timewindow = 1e6;
  std::unique_ptr<TimeWeightedMovingAverage<double>> twma;
  twma = std::make_unique<TimeWeightedMovingAverage<double>>(timewindow);

  int64_t ts = 1e9;
  double obj = 100;
  EXPECT_EQ(std::isnan(twma->GetAverage()), true);
  EXPECT_EQ(std::isnan(twma->GetAverage(ts)), true);
  twma->Add(ts + prev_ts, obj);
  EXPECT_EQ(twma->Size(), 1);
  EXPECT_EQ(twma->GetWindowSize(), 1e6);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), false);

  EXPECT_EQ(twma->GetAverage(), 100);
  EXPECT_EQ(twma->GetLastData(), 100);
  EXPECT_EQ(twma->GetFirstData(), 100);
  EXPECT_EQ(twma->GetLastTs(), 17000e6);
  EXPECT_EQ(twma->GetFirstTs(), 17000e6);
}

TEST(TimeWeightedMovingAverageTest, Basic_Not_Ready2) {
  int64_t timewindow = 1e6;
  std::unique_ptr<TimeWeightedMovingAverage<double>> twma;
  twma = std::make_unique<TimeWeightedMovingAverage<double>>(timewindow);

  int64_t ts = 1e9;
  double obj = 100;
  twma->Add(ts + prev_ts, obj);

  int64_t ts2 = 1001 * 1e6;
  double obj2 = 200;
  twma->Add(ts2 + prev_ts, obj2);

  EXPECT_EQ(twma->Size(), 2);
  EXPECT_EQ(twma->GetWindowSize(), 1e6);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), false);

  EXPECT_EQ(twma->GetAverage(), 100);
  EXPECT_EQ(twma->GetLastData(), 200);
  EXPECT_EQ(twma->GetFirstData(), 100);
  EXPECT_EQ(twma->GetLastTs(), 17001e6);
  EXPECT_EQ(twma->GetFirstTs(), 17000e6);
}

TEST(TimeWeightedMovingAverageTest, Basic_Ready) {
  int64_t timewindow = 1e6;
  std::unique_ptr<TimeWeightedMovingAverage<double>> twma;
  twma = std::make_unique<TimeWeightedMovingAverage<double>>(timewindow);
  EXPECT_EQ(twma->GetWindowSize(), 1e6);

  int64_t ts = 1e9;
  double obj = 100;
  twma->Add(ts + prev_ts, obj);

  int64_t ts2 = 2e9;
  double obj2 = 200;
  twma->Add(ts2 + prev_ts, obj2);

  EXPECT_EQ(twma->Size(), 1);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), true);

  EXPECT_EQ(twma->GetAverage(), 200);
  EXPECT_EQ(twma->GetAverage(ts2 + prev_ts), 200);
  EXPECT_EQ(twma->GetAverage(ts2 + prev_ts + 1), 200);
  EXPECT_EQ(twma->GetLastData(), 200);
  EXPECT_EQ(twma->GetFirstData(), 200);
  EXPECT_EQ(twma->GetLastTs(), 18000e6);
  EXPECT_EQ(twma->GetFirstTs(), 18000e6);
}

TEST(TimeWeightedMovingAverageTest, Intermediate) {
  int64_t timewindow = 1e7;
  std::unique_ptr<TimeWeightedMovingAverage<double>> twma;
  twma = std::make_unique<TimeWeightedMovingAverage<double>>(timewindow);
  EXPECT_EQ(twma->GetWindowSize(), 10e6);

  int64_t ts = 1e9;
  double obj = 100;
  twma->Add(ts + prev_ts, obj);

  int64_t ts2 = 2e9;
  double obj2 = 200;
  twma->Add(ts2 + prev_ts, obj2);

  int64_t ts3 = 2001 * 1e6;
  double obj3 = 300;
  twma->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(twma->Size(), 2);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), true);
  EXPECT_EQ(twma->GetAverage(), 200);

  EXPECT_EQ(twma->GetLastData(), 300);
  EXPECT_EQ(twma->GetFirstData(), 200);
  EXPECT_EQ(twma->GetLastTs(), 18001e6);
  EXPECT_EQ(twma->GetFirstTs(), 18000e6);

  int64_t ts4 = 2011 * 1e6;
  double obj4 = 400;
  twma->Add(ts4 + prev_ts, obj4);
  EXPECT_EQ(twma->Size(), 2);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), true);
  EXPECT_EQ(twma->GetAverage(), 300);

  EXPECT_EQ(twma->GetLastData(), 400);
  EXPECT_EQ(twma->GetFirstData(), 300);
  EXPECT_EQ(twma->GetLastTs(), 18011e6);
  EXPECT_EQ(twma->GetFirstTs(), 18001e6);
}

TEST(TimeWeightedMovingAverageTest, Intermediate2) {
  int64_t timewindow = 1e7;
  std::unique_ptr<TimeWeightedMovingAverage<double>> twma;
  twma = std::make_unique<TimeWeightedMovingAverage<double>>(timewindow);
  EXPECT_EQ(twma->GetWindowSize(), 10e6);

  int64_t ts = 1e9;
  double obj = 100;
  twma->Add(ts + prev_ts, obj);

  int64_t ts2 = 1001 * 1e6;
  double obj2 = 200;
  twma->Add(ts2 + prev_ts, obj2);

  EXPECT_EQ(twma->Size(), 2);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), false);
  EXPECT_EQ(twma->GetAverage(), 100);

  EXPECT_EQ(twma->GetLastData(), 200);
  EXPECT_EQ(twma->GetFirstData(), 100);
  EXPECT_EQ(twma->GetLastTs(), 17001e6);
  EXPECT_EQ(twma->GetFirstTs(), 17000e6);

  int64_t ts3 = 1002 * 1e6;
  double obj3 = 300;
  twma->Add(ts3 + prev_ts, obj3);
  EXPECT_EQ(twma->Size(), 3);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), false);
  EXPECT_EQ(twma->GetAverage(), 150);

  EXPECT_EQ(twma->GetLastData(), 300);
  EXPECT_EQ(twma->GetFirstData(), 100);
  EXPECT_EQ(twma->GetLastTs(), 17002e6);
  EXPECT_EQ(twma->GetFirstTs(), 17000e6);

  int64_t ts4 = 1003 * 1e6;
  double obj4 = 400;
  twma->Add(ts4 + prev_ts, obj4);
  EXPECT_EQ(twma->Size(), 4);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), false);
  EXPECT_EQ(twma->GetAverage(), 200);

  EXPECT_EQ(twma->GetLastData(), 400);
  EXPECT_EQ(twma->GetFirstData(), 100);
  EXPECT_EQ(twma->GetLastTs(), 17003e6);
  EXPECT_EQ(twma->GetFirstTs(), 17000e6);

  int64_t ts5 = 1011 * 1e6;
  double obj5 = 500;
  twma->Add(ts5 + prev_ts, obj5);
  EXPECT_EQ(twma->Size(), 4);
  EXPECT_EQ(twma->Empty(), false);
  EXPECT_EQ(twma->Ready(), true);

  double expect = (400 * 8 + 300 * 1 + 200 * 1) / 10.0;
  double diff = std::abs(twma->GetAverage() - expect);
  EXPECT_LT(diff, 1e-6);

  double expect2 = (500 * 5 + 400 * 8 + 300 * 1 + 200 * 1) / 15.0;
  double diff2 = std::abs(twma->GetAverage((1011 + 5) * 1e6 + prev_ts) - expect2);
  EXPECT_LT(diff2, 1e-6);

  EXPECT_EQ(twma->GetLastData(), 500);
  EXPECT_EQ(twma->GetFirstData(), 200);
  EXPECT_EQ(twma->GetLastTs(), 17011e6);
  EXPECT_EQ(twma->GetFirstTs(), 17001e6);
}

TEST(ExponentialMovingAverageTest, Basic) {
  double alpha = 0.4;
  int64_t update_interval = 0;
  std::unique_ptr<ExponentialMovingAverage> ema;
  ema = std::make_unique<ExponentialMovingAverage>(alpha, update_interval);

  int64_t ts = 1;
  double v = 2;
  ema->Update(ts, v);
  EXPECT_EQ(round3(ema->Get()), 2);
}

TEST(ExponentialMovingAverageTest, Basic2) {
  double alpha = 0.4;
  int64_t update_interval = 0;
  std::unique_ptr<ExponentialMovingAverage> ema;
  ema = std::make_unique<ExponentialMovingAverage>(alpha, update_interval);

  int64_t ts = 1;
  double v = 2;
  ema->Update(ts, v);
  EXPECT_EQ(round3(ema->Get()), 2);

  int64_t ts2 = 2;
  double v2 = 3;
  ema->Update(ts2, v2);
  EXPECT_EQ(round3(ema->Get()), 2.4);

  int64_t ts3 = 3;
  double v3 = 4;
  ema->Update(ts3, v3);
  EXPECT_EQ(round3(ema->Get()), 3.04);
}

}  // namespace coin2::strategy::util